/**
 * *****************************************
 * 链表结构
 * @module Link
 * @date ###### Thu Oct 12 15:15:49 CST 2017
 * @author jinglf000
 * insert removeAt indexOf
 * *****************************************
 */

/**
 * @desc 链表的节点结构
 * @param {any} element
 * @return {Object} {element, next, prev}
 */
function Node(element) {
  this.element = element;
  this.next = null;
  this.prev = null;
}
/**
 * @class Link 代表链表结构，节点从0开始
 */
class Link {
  constructor() {
    this.end = null;
    this.head = null;
    this.length = 0;
  }
  /**
   * 添加节点
   * @param {*} element 节点
   */
  append(element) {
    const currentNode = new Node(element);
    if (this.head === null) {
      this.head = currentNode;
      currentNode.prev = this;
    } else {
      currentNode.prev = this.end;
      this.end.next = currentNode;
    }
    this.length += 1;
    this.end = currentNode;
  }
  /**
   * 把内容转换为字符串
   * @returns {string} 返回字符串
   */
  toString() {
    let current = this.head;
    let str = '';
    while (current) {
      str += current.element + (current.next ? ',' : '');
      current = current.next;
    }
    return str;
  }
  /**
   * 删除制定位置的节点
   * @param {Number} num 要删除的节点次序
   * @return {Element} 返回删除的节点内容
   */
  removeAt(num) {
    if (num < 0 || num > this.length - 1) {
      return null;
    }
    let cur = this.head;
    for (let i = 0; i < this.length; i += 1) {
      if (i === num) {
        // 缓存当前值，解构赋值
        const { element, prev } = cur;
        // 确定上一个值的指针
        if (prev.next) {
          prev.next = cur.next;
        } else {
          prev.head = cur.next;
        }
        cur = cur.next;
        // 确定下一个值得指针
        if (cur) cur.prev = prev;
        // 确定end指针
        if (i === this.length - 1) {
          this.end = prev;
        }
        // 修改整体长度
        this.length -= 1;
        return element;
      }
      cur = cur.next;
    }
  }
  /**
   * 获取制定节点的元素
   * @param {Number} num 节点序号
   * @returns {node} 返回节点
   */
  _getNode(num) {
    if (num < 0 || num > this.length - 1) {
      return null;
    }
    let cur = this.head;
    for (let i = 0; i < num; i += 1) {
      cur = cur.next;
    }
    return cur;
  }
  /**
   * 获取节点元素
   * @param {Number} num 要获取的节点
   * @return {element} 返回节点内容
   */
  getAt(num) {
    const node = this._getNode(num);
    return node ? node.element : null;
  }
  /**
   * 替换元素
   * @param {Number} num 要替换的序号
   * @param {*} element 替换的元素
   * @return {Boolean} <true|false> true替换成功，false替换失败
   */
  replace(num, element) {
    if (num < 0 || num > this.length - 1) {
      return false;
    }
    let cur = this.head;
    for (let i = 0; i < num; i += 1) {
      cur = cur.next;
    }
    cur.element = element;
    return true;
  }
  /**
   * 在num后插入元素
   * @param {Number} num 要插入的位置
   * @param {*} element
   * @return {Boolean} <true|false>
   */
  insert(num, element) {
    const newNode = new Node(element);
    if (num < 0) {
      const oldNode = this.head;
      newNode.prev = this;
      newNode.next = oldNode;
      oldNode.prev = newNode;
      this.head = newNode;
    } else if (num >= this.length - 1) {
      this.append(element);
    } else {
      const node = this._getNode(num);
      newNode.prev = node;
      newNode.next = node.next;
      node.next.prev = newNode;
      node.next = newNode;
    }
    this.length += 1;
  }
  /**
   * myName 静态方法
   */
  static myName() {
    return this.name;
  }
}

// Link.

// const link = new Link();

// link.append(12);
// link.append(56);
// link.insert(-9,152);
// console.log(link.toString());
// link.insert(0, 'first blood');
// console.log(link.toString());
// link.insert(1, 'second blood');
// console.log(link.toString());


// console.log(link.removeAt(1));
// console.log(link.getAt(1));
// link.append(777);

// console.log(link.replace(1, 'hello world'));
// link.append(888);

// console.log(link.getAt(1));
// console.log(link.toString());
module.exports = Link;
